package com.suray.wcs.service.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.suray.basic.wcs.path.enums.Direction;
import com.suray.basic.wcs.path.enums.NodeType;
import com.suray.commin.core.utils.SurayBeanUtils;
import com.suray.wcs.service.pojo.BaseEum;
import com.suray.wcs.service.system.bo.PageResultBO;
import com.suray.wcs.service.system.bo.SingleRuleBO;
import com.suray.wcs.service.system.entity.NodeDB;
import com.suray.wcs.service.system.entity.SingleRuleDB;
import com.suray.wcs.service.system.entity.ZoneRuleDB;
import com.suray.wcs.service.system.mapper.NodeDBMapper;
import com.suray.wcs.service.system.mapper.SingleRuleMapper;
import com.suray.wcs.service.system.service.ISingleRuleService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service
public class SingleRuleServiceImpl extends ServiceImpl<SingleRuleMapper, SingleRuleDB> implements ISingleRuleService {
    @Resource
    private SingleRuleMapper singleRuleMapper;
    @Resource
    private NodeDBMapper nodedbMapper;

    @Override
    public List<SingleRuleDB> getSingleRuleList(SingleRuleDB singleRuleDB) {
        QueryWrapper<SingleRuleDB> queryWrapper = new QueryWrapper();

        if(singleRuleDB.getGridxStart() != null){
            queryWrapper.lambda().eq(SingleRuleDB::getGridxStart,singleRuleDB.getGridxStart());
        }
        if(singleRuleDB.getGridyStart() != null){
            queryWrapper.lambda().eq(SingleRuleDB::getGridyStart,singleRuleDB.getGridyStart());
        }
        if(singleRuleDB.getGridz() != null && !singleRuleDB.getGridz().equals("")){
            String z = singleRuleDB.getGridz();
            queryWrapper.and(wrapper -> wrapper.lambda().like(SingleRuleDB::getGridz, "," + z + ",")
                    .or().like(SingleRuleDB::getGridz, "," + z + "]")
                    .or().like(SingleRuleDB::getGridz, "[" + z + ",")
                    .or().like(SingleRuleDB::getGridz, "[" + z + "]")
            );
        }
        return singleRuleMapper.selectList(queryWrapper);
    }

    @Override
    public List<BaseEum> getSingleRuleDirectionList() {
        List<Direction> directions = (Arrays.asList(Direction.values()));
        List<BaseEum> baseEums = new ArrayList<BaseEum>();
        for (Direction direction : directions) {
            baseEums.add(new BaseEum(direction.getVal(), direction.getDescription()));
        }
        return baseEums;
    }

    @Override
    public SingleRuleBO addSingleRule(SingleRuleBO singleRuleBO) {
        SingleRuleDB singleRuleDB = SurayBeanUtils.copyProperties(singleRuleBO, SingleRuleDB.class);
        singleRuleDB.setGridz(JSON.toJSONString(singleRuleBO.getGridzList()));
        singleRuleDB.setUpdateTime(new Date());
        singleRuleMapper.insert(singleRuleDB);
        return singleRuleBO;
    }

    @Override
    public SingleRuleBO updateSingleRule(SingleRuleBO singleRuleBO) {
        SingleRuleDB singleRuleDB = SurayBeanUtils.copyProperties(singleRuleBO, SingleRuleDB.class);
        singleRuleDB.setGridz(JSON.toJSONString(singleRuleBO.getGridzList()));
        singleRuleMapper.updateById(singleRuleDB);
        return singleRuleBO;
    }

    @Override
    public void deleteSingleRule(List<Integer> ids) {
        singleRuleMapper.deleteBatchIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applySingleRule(List<Integer> ids) {
       List<SingleRuleDB> singleRuleDBS =  singleRuleMapper.selectBatchIds(ids);
        Collections.sort(singleRuleDBS, (o1, o2) -> {
            int diff = o1.getRuleId() - o2.getRuleId();
            if(diff > 0) {
                return 1;
            } else if(diff < 0) {
                return -1;
            }
            return 0;
        });

        for (SingleRuleDB singleRuleDB : singleRuleDBS) {
            String singleNo;
            boolean isX = true;
            if(Direction.LEFT.getVal().equals(singleRuleDB.getDirection()) ||  Direction.RIGHT.getVal().equals(singleRuleDB.getDirection())) {
                singleNo = "x"+singleRuleDB.getGridxStart()+ "_" + singleRuleDB.getGridxEnd() + "_" ;
            } else {
                isX = false;
                singleNo = "y"+singleRuleDB.getGridyStart()+ "_" + singleRuleDB.getGridyEnd() + "_" ;
            }
            QueryWrapper<NodeDB> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().ge(NodeDB::getGridx, singleRuleDB.getGridxStart()).le(NodeDB::getGridx, singleRuleDB.getGridxEnd())
            .ge(NodeDB::getGridy, singleRuleDB.getGridyStart()).le(NodeDB::getGridy, singleRuleDB.getGridyEnd())
            .in(NodeDB::getGridz, JSONArray.parseArray(singleRuleDB.getGridz(), Integer.class))
            .eq(NodeDB::getGridType, NodeType.P.getCode());
            List<NodeDB> nodeDBS = nodedbMapper.selectList(queryWrapper);
            for (NodeDB nodeDB : nodeDBS) {
                NodeDB newNodeDB = new NodeDB();
                newNodeDB.setNodeId(nodeDB.getNodeId());
                if(isX) {
                    newNodeDB.setSingleNo(singleNo + nodeDB.getGridy() + "_" + nodeDB.getGridz());
                } else {
                    newNodeDB.setSingleNo(singleNo + nodeDB.getGridx() + "_" + nodeDB.getGridz());
                }
                newNodeDB.setSingleOrder(singleRuleDB.getDirection());
                nodedbMapper.updateById(newNodeDB);
            }
        }
    }

    @Override
    public PageResultBO<SingleRuleBO> getSingleRuleInfo(Integer ruleId) {
        QueryWrapper<SingleRuleDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SingleRuleDB::getRuleId,ruleId);
        List<SingleRuleDB> singleRuleDBS = singleRuleMapper.selectList(queryWrapper);
        SingleRuleBO singleRuleBO = new SingleRuleBO();
        BeanUtils.copyProperties(singleRuleDBS.get(0), singleRuleBO);
        singleRuleBO.setGridzList(JSON.parseArray(singleRuleDBS.get(0).getGridz(), Integer.class));
        PageResultBO<SingleRuleBO> pageResultBO = new PageResultBO<>();
        pageResultBO.setData(singleRuleBO);
        return pageResultBO;
    }
}
